`timescale 1ns / 1ns
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/11/09 09:45:49
// Design Name: 
// Module Name: tb_uart
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_uart();

/****仿真语法、产生时钟与复位****/

localparam      CLK_PERIOD      =   20                          ;
localparam      SYSTEM_CLK      =   50_000_000                  ;
localparam      UART_BAUDRATE   =   9600                        ;   // 波特率
localparam      UART_DATAWIDTH  =   8                           ;   // 有效数据位位宽
localparam      UART_CHECK      =   0                           ;   // 奇偶校验位，0-没有校验位 1-奇校验位 2-偶校验位
localparam      UART_STOP_WIDTH =   1                           ;   // 停止位位宽，1或者2
localparam      CLK_DIV_UART    =   SYSTEM_CLK / UART_BAUDRATE  ;

reg                                 i_clk           ;
reg  [UART_DATAWIDTH - 1 : 0]       r_user_tx_data  ;
reg                                 r_user_tx_valid ;

wire                                w_tx_clk        ;
wire                                w_tx_rst        ; 
wire                                w_user_tx_ready ;

wire [UART_DATAWIDTH - 1 : 0]       w_user_rx_data  ;
wire                                w_user_rx_valid ;


always begin//过程语句，只在仿真里可以使用，不可综合
    i_clk = 0;
    #(CLK_PERIOD/2);
    i_clk = 1;
    #(CLK_PERIOD/2);
end
clk_pll_50 u_clk_pll_50
(    
    // Clock in ports
    .clk_in1    (i_clk      ) ,       // input clk_in1
    // Status and control signals
    .locked     (clk_locked ) ,       // output locked
    // Clock out ports
    .clk_out1   (w_clk_50MHz)         // output clk_out1
    );      

assign  w_clk_rst = ~clk_locked   ;

clk_div_module #(
    .CLK_DIV_NUM                ( CLK_DIV_UART      ))
 u_rx_clk_div_module (          
    .i_clk                      ( w_clk_50MHz       ),
    .i_rst                      ( w_clk_rst         ),
            
    .o_clk                      ( w_rx_clk          )
);          
            
clk_div_module #(           
    .CLK_DIV_NUM                ( CLK_DIV_UART      ))
 u_tx_clk_div_module (          
    .i_clk                      ( w_clk_50MHz       ),
    .i_rst                      ( w_clk_rst         ),
            
    .o_clk                      ( w_tx_clk          )
);


assign w_user_active = r_user_tx_valid & w_user_tx_ready;

/****激励信号****/
always@(posedge w_tx_clk,posedge w_tx_rst)
begin
    if(w_tx_rst)
        r_user_tx_data <= 'd0;
    else if(w_user_active)
        r_user_tx_data <= r_user_tx_data + 1;
    else 
        r_user_tx_data <= r_user_tx_data;
end

always@(posedge w_tx_clk,posedge w_tx_rst)
begin
    if(w_tx_rst)
        r_user_tx_valid <= 'd0;
    else if(w_user_active)
        r_user_tx_valid <= 'd0;
    else if(w_user_tx_ready)
        r_user_tx_valid <= 'd1;
    else 
        r_user_tx_valid <= r_user_tx_valid;
end


txdat_module #(
    .SYSTEM_CLK                 ( SYSTEM_CLK        ),
    .UART_BAUDRATE              ( UART_BAUDRATE     ),
    .UART_DATAWIDTH             ( UART_DATAWIDTH    ),
    .UART_CHECK                 ( UART_CHECK        ),
    .UART_STOP_WIDTH            ( UART_STOP_WIDTH   ))
 u_txdat_module (
    .i_clk                      ( i_clk             ),
    .i_user_tx_data             ( r_user_tx_data    ),
    .i_user_tx_valid            ( r_user_tx_valid   ),

    .o_uart_tx                  ( o_uart_tx         ),
    .o_user_tx_ready            ( w_user_tx_ready   ),
    .o_tx_clk                   ( w_tx_clk          ),
    .o_tx_rst                   ( w_tx_rst          )
);

rxdat_module #(
    .SYSTEM_CLK                 ( SYSTEM_CLK        ),
    .UART_BAUDRATE              ( UART_BAUDRATE     ),
    .UART_DATAWIDTH             ( UART_DATAWIDTH    ),
    .UART_CHECK                 ( UART_CHECK        ),
    .UART_STOP_WIDTH            ( UART_STOP_WIDTH   ))
 u_rxdat_module (
    .i_clk                      ( i_clk             ),
    .i_uart_rx                  ( o_uart_tx         ),

    .o_user_rx_data             ( w_user_rx_data    ),
    .o_user_rx_valid            ( w_user_rx_valid   )
);

endmodule
